#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <sqlite3.h>
#import <QuartzCore/QuartzCore.h>
#import <LockInfo/Plugin.h>

#import "FWPlugin.h"
#import "FWDetailListView.h"
#import "FWRoundedLabel.h"
#import "FWColorIconView.h"


static CGFloat iPhoneCellInset = 10;
static CGFloat iPhoneCellBorder = 10;

static CGFloat iPadCellInset = 45;
static CGFloat iPadCellBorder = 10;

static CGFloat iconPadding = 8;

static CGFloat const kNavButtonWidth = 44.0;


NSString* const FWDetailListViewFieldTitle = @"title";
NSString* const FWDetailListViewFieldMessage = @"message";
NSString* const FWDetailListViewFieldValue = @"value";
NSString* const FWDetailListViewFieldNoBold = @"nobold";
NSString* const FWDetailListViewFieldSize = @"size";
NSString* const FWDetailListViewFieldIcon = @"icon";
NSString* const FWDetailListViewFieldLines = @"lines";
NSString* const FWDetailListViewFieldColor = @"color";
NSString* const FWDetailListViewFieldBGColor = @"bgcolor";
NSString* const FWDetailListViewFieldProgress = @"progress";
NSString* const FWDetailListViewFieldSwitch = @"switch";
NSString* const FWDetailListViewFieldSelected = @"selected";
NSString* const FWDetailListViewFieldTitleInfo = @"titleinfo";
NSString* const FWDetailListViewFieldIsLink = @"link";
NSString* const FWDetailListViewFieldIsBackLink = @"back";

NSString* const FWDetailListViewSectionTitle = @"section";
NSString* const FWDetailListViewSectionContents = @"contents";


static CGSize const ProgressBarSize = CGSizeMake(150, 9);
static CGSize const iPadSwitchSize = CGSizeMake(100, 27);
static CGSize const iPhoneSwitchSize = CGSizeMake(100, 27);

static CGFloat const NavigationAnimationDuration = 0.4;
static NSString* const NavigationTransitionType = kCATransitionPush;
static NSString* const NavigationTimingFunctionName = kCAMediaTimingFunctionDefault;


@implementation FWDetailListView

@synthesize delegate, index, application, list, view, navControl, caption, navBar, sections, linkStack, reloadViewOffset, reloadViewAnimated;


// ******************************************************************************************
#pragma mark -
#pragma mark Helper methods to construct standard section types

+ (NSDictionary*)sectionEntryForElements:(NSArray*)elements
{
    return [[[NSDictionary alloc] initWithObjectsAndKeys:elements, FWDetailListViewSectionContents, nil] autorelease];
}

+ (NSDictionary*)sectionEntryForElements:(NSArray*)elements withTitle:(NSString*)title
{
    return [[[NSDictionary alloc] initWithObjectsAndKeys:elements, FWDetailListViewSectionContents,
             title, FWDetailListViewSectionTitle, nil] autorelease];
}


// ******************************************************************************************
#pragma mark -
#pragma mark Initialisation and object management

- (id)initWithFrame:(CGRect)r list:(NSArray*)l index:(NSInteger)i caption:(NSString*)capt application:(FWApplication*)app delegate:(id<FWDetailListViewDelegate>)d
{
    if ((self = [super initWithFrame:r])) {
        self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        self.autoresizesSubviews = YES;
        
        self.list = l;
        self.delegate = d;
        self.application = app;
        self.caption = capt;
        [self buildPreview:r];
        self.index = i;
        
        self.reloadViewOffset = 0;
        self.reloadViewAnimated = YES;
        
        self.linkStack = [[[NSMutableArray alloc] init] autorelease];
    }

    return self;
}

- (id)initWithFrame:(CGRect)r list:(NSArray*)l index:(NSInteger)i application:(FWApplication*)app delegate:(id<FWDetailListViewDelegate>)d
{
    if ((self = [self initWithFrame:r list:l index:i caption:@"" application:app delegate:d])) {
    }
    
    return self;
}

- (void)dealloc
{
    [delegate release];
    [list release];
    [view release];
    [application release];
    [navControl release];
    [sections release];
    [navBar release];
    [caption release];
    [linkStack release];
    
    [super dealloc];
}


// ******************************************************************************************
#pragma mark -
#pragma mark Attribute access and support

- (void)setCaption:(NSString*)newCaption
{
    NSBundle* bundle = [NSBundle bundleForClass:[self class]];
    [caption release];
    caption = localize(bundle, newCaption);
    [caption retain];
    
    if (self.navBar) {
        UINavigationItem* nav = self.navBar.topItem;
        nav.title = caption;
    }
}

- (void)setIndex:(NSInteger)i
{
    index = i;
    
    if ([self.list count] > 1) {
        [self.navControl setEnabled:(i > 0) forSegmentAtIndex:0];
        [self.navControl setEnabled:(i < ((int)[self.list count] - 1)) forSegmentAtIndex:1];
    }
    
    self.sections = [delegate dataForDetailListPage:[list objectAtIndex:i] application:self.application];
    
    if ([linkStack count] == 0) {
        NSRange range = [caption rangeOfString:@"%i"];
        if (range.location != NSNotFound) {
            UINavigationItem* nav = self.navBar.topItem;
            nav.title = [NSString stringWithFormat:caption, i+1, [self.list count]];
        }
    }
    
    [self reloadData:reloadViewAnimated];
}


// ******************************************************************************************
#pragma mark -
#pragma mark Main window layout

- (void)buildPreview:(CGRect)rect
{
    NSBundle* bundle = [NSBundle bundleForClass:[self class]];
    
    UIBarButtonItem* doneBtn = [[[UIBarButtonItem alloc]
                                 initWithTitle:localize(bundle, @"Detail/Button/Done")
                                 style:UIBarButtonItemStyleBordered 
                                 target:self
                                 action:@selector(doneClicked)] autorelease];
    
    UIBarButtonItem* cancelBtn = [[[UIBarButtonItem alloc]
                                   initWithTitle:localize(bundle, @"Detail/Button/Cancel")
                                   style:UIBarButtonItemStyleBordered 
                                   target:self
                                   action:@selector(cancelClicked)] autorelease];
    
    UIBarButtonItem* selectBtn = [[[UIBarButtonItem alloc]
                                   initWithTitle:localize(bundle, @"Detail/Button/Select")
                                   style:UIBarButtonItemStyleBordered 
                                   target:self
                                   action:@selector(selectClicked)] autorelease];
    
    UIImage* btnUp = [UIImage imageWithContentsOfFile:@"/Applications/MobileMail.app/arrowup.png"];								  
    UIImage* btnDown = [UIImage imageWithContentsOfFile:@"/Applications/MobileMail.app/arrowdown.png"];								  
    self.navControl = [[[UISegmentedControl alloc]
                        initWithItems:
                        [NSArray arrayWithObjects:
                         btnUp,
                         btnDown,
                         nil]] autorelease];
    
    if ((btnUp == nil) || (btnDown == nil))
        self.navControl = [[[UISegmentedControl alloc]
                            initWithItems:
                            [NSArray arrayWithObjects:
                             //                             localize(bundle, @"Detail/Button/Up"),
                             //                             localize(bundle, @"Detail/Button/Down"),
                             @"U", @"D",
                             nil]] autorelease];
    
    self.navControl.segmentedControlStyle = UISegmentedControlStyleBar;
    self.navControl.momentary = YES;
    [self.navControl setWidth:kNavButtonWidth forSegmentAtIndex:0];
    [self.navControl setWidth:kNavButtonWidth forSegmentAtIndex:1];
    
    [self.navControl addTarget:self
                        action:@selector(navigateClicked:)
              forControlEvents:UIControlEventValueChanged];
    
    UIBarButtonItem* navBtn = [[[UIBarButtonItem alloc] initWithCustomView:self.navControl] autorelease];
    
    const CGFloat toolbarHeight = 44;
    CGRect navBarFrame = CGRectMake(0, 0, rect.size.width, toolbarHeight);
    CGRect taskBarFrame = CGRectMake(0, rect.size.height - toolbarHeight, rect.size.width, toolbarHeight);
    CGRect scrollFrame = CGRectMake(0, navBarFrame.size.height, rect.size.width, rect.size.height - taskBarFrame.size.height - navBarFrame.size.height);
    
    UINavigationBar* nav = [[[UINavigationBar alloc] initWithFrame:navBarFrame] autorelease];
    nav.delegate = self;
    nav.autoresizingMask = UIViewAutoresizingFlexibleWidth;
    nav.barStyle = UIBarStyleBlackOpaque;
    self.navBar = nav;
    
    UINavigationItem* navItem = [[[UINavigationItem alloc] initWithTitle:self.caption] autorelease];
    
    if ([delegate respondsToSelector:@selector(cancelClicked:sections:)]) {
        navItem.leftBarButtonItem = cancelBtn;
        
        if ([delegate respondsToSelector:@selector(doneClicked:sections:)])
            navItem.rightBarButtonItem = doneBtn;
        else if ([delegate respondsToSelector:@selector(selectClicked:sections:)])
            navItem.rightBarButtonItem = selectBtn;
    }
    else if ([delegate respondsToSelector:@selector(doneClicked:sections:)])
        navItem.leftBarButtonItem = doneBtn;
    
    if ([self.list count] > 1)
        navItem.rightBarButtonItem = navBtn;
    
    [nav setItems:[NSArray arrayWithObjects:navItem, nil] animated:NO];
    [self addSubview:nav];
    
    //#ifdef DEBUG
    //    UIToolbar* task = [[[UIToolbar alloc] initWithFrame:taskBarFrame] autorelease];
    //    task.autoresizingMask = UIViewAutoresizingFlexibleWidth;
    //    task.barStyle = UIBarStyleBlackOpaque;
    //    task.items = [NSArray arrayWithObjects:
    //                  flexibleSpace,
    //                  nil];
    //    [self addSubview:task];
    //#else
    scrollFrame.size.height += taskBarFrame.size.height;
    //#endif
    
    UITableView* tableView = [[UITableView alloc] initWithFrame:scrollFrame style:UITableViewStyleGrouped];
    tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    tableView.autoresizesSubviews = YES;
    tableView.dataSource = self;
    tableView.delegate = self;
    tableView.allowsSelection = YES;
    
    [self addSubview:tableView];
    self.view = tableView;
    
    [tableView release];
}

- (void)setFrame:(CGRect)newFrame
{
    BOOL shouldReload = !CGRectEqualToRect(self.frame, newFrame);
    [super setFrame:newFrame];

    // If the size of the frame has changed then reload the contents which
    // will ensure any contents will be re-laid out
    if (shouldReload)
        [self.view reloadData];
}


// ******************************************************************************************
#pragma mark -
#pragma mark Tableview section information

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return [self.sections count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    NSDictionary* sect = [self.sections objectAtIndex:section];
    NSArray* contents = [sect objectForKey:FWDetailListViewSectionContents];
    return [contents count];
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    NSDictionary* sect = [self.sections objectAtIndex:section];
    NSString* title = [sect objectForKey:FWDetailListViewSectionTitle];
    return title;
}

- (CGFloat)tableView:(UITableView*)tableView heightForHeaderInSection:(NSInteger)section
{
    NSDictionary* sect = [self.sections objectAtIndex:section];
    NSString* title = [sect objectForKey:FWDetailListViewSectionTitle];
    
    if (title)
        return [UIFont boldSystemFontOfSize:[UIFont labelFontSize]].leading + 6;
    else {
        if (section == 0)
            return 4.0;
        else
            return 1.0;
    }
}

- (CGFloat)tableView:(UITableView*)tableView heightForFooterInSection:(NSInteger)section
{
    return 2.0;
}

- (UIView*)tableView:(UITableView*)tableView viewForHeaderInSection:(NSInteger)section
{
    NSDictionary* sect = [self.sections objectAtIndex:section];
    NSString* title = [sect objectForKey:FWDetailListViewSectionTitle];
    
    if (title)
        return nil;
    else
        return [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)] autorelease];
}

- (UIView*)tableView:(UITableView*)tableView viewForFooterInSection:(NSInteger)section
{
    return [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)] autorelease];
}


// ******************************************************************************************
#pragma mark -
#pragma mark Tableview element layout

- (CGSize)tableView:(UITableView *)tableView constraintForTextFieldWithIcon:(UIImage*)icon progress:(BOOL)progress swtch:(BOOL)swtch selected:(BOOL)selected
{
    BOOL iPad = (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPhone);
    CGFloat cellInset = iPad ? iPadCellInset : iPhoneCellInset;
    CGFloat cellBorder = iPad ? iPadCellBorder : iPhoneCellBorder;

    CGFloat width = tableView.frame.size.width - 2 * (cellInset + cellBorder);
    CGFloat iconWidth = (icon != nil) ? (icon.size.width + iconPadding): 0;
    CGSize constraint = CGSizeMake(width - iconWidth, MAXFLOAT);
    
    if (progress)
        constraint.width -= ProgressBarSize.width;
    else if (swtch) 
        constraint.width -= iPad ? iPadSwitchSize.width : iPhoneSwitchSize.width;
    else if (selected) 
        constraint.width -= 32;
    
    return constraint;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    BOOL iPad = (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPhone);
    CGFloat cellInset = iPad ? iPadCellInset : iPhoneCellInset;
    CGFloat cellBorder = iPad ? iPadCellBorder : iPhoneCellBorder;
    CGFloat width = tableView.frame.size.width - 2 * (cellInset + cellBorder);

    NSDictionary* section = [self.sections objectAtIndex:indexPath.section];
    NSArray* contents = [section objectForKey:FWDetailListViewSectionContents];

    NSDictionary* elem = [contents objectAtIndex:indexPath.row];
    
    NSString* title = [elem objectForKey:FWDetailListViewFieldTitle];
    NSString* message = [elem objectForKey:FWDetailListViewFieldMessage];
    NSString* value = [elem objectForKey:FWDetailListViewFieldValue];
    NSNumber* nobold = [elem objectForKey:FWDetailListViewFieldNoBold];
    NSNumber* swtch = [elem objectForKey:FWDetailListViewFieldSwitch];
    NSNumber* progress = [elem objectForKey:FWDetailListViewFieldProgress];
    NSNumber* size = [elem objectForKey:FWDetailListViewFieldSize];
    if (size == nil)
        size = [NSNumber numberWithFloat:[UIFont labelFontSize]];
    
    if (progress || swtch || (value == nil) || ([value length] == 0)) {
        UIImage* newIcon = [elem objectForKey:FWDetailListViewFieldIcon];
        
        // If we have a message then use it as the basis for the title size
        if (message)
            title = message;
        
        UIFont* font = nobold ? [UIFont systemFontOfSize:size.floatValue] : [UIFont boldSystemFontOfSize:size.floatValue];

        CGSize constraintSize = [self tableView:tableView 
                 constraintForTextFieldWithIcon:newIcon
                                       progress:progress != nil
                                          swtch:swtch != nil
                                       selected:NO];

        CGSize titleSize = [title sizeWithFont:font
                             constrainedToSize:constraintSize
                                 lineBreakMode:UILineBreakModeWordWrap];
        
        return titleSize.height + cellBorder * 2;
    }
    else {
        CGSize titleSize = [title sizeWithFont:[UIFont boldSystemFontOfSize:[UIFont labelFontSize]]];
        CGSize constraint = CGSizeMake(width - titleSize.width - 6, MAXFLOAT);
        CGSize detailSize = [value sizeWithFont:[UIFont systemFontOfSize:size.floatValue] 
                              constrainedToSize:constraint
                                  lineBreakMode:UILineBreakModeWordWrap];
        
        if (titleSize.height > detailSize.height)
            return titleSize.height + cellBorder * 2;
        else
            return detailSize.height + cellBorder * 2;
    }
}


// ******************************************************************************************
#pragma mark -
#pragma mark Tableview element access

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    BOOL iPad = (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPhone);

    NSDictionary* section = [self.sections objectAtIndex:indexPath.section];
    NSArray* contents = [section objectForKey:FWDetailListViewSectionContents];
    NSDictionary* elem = [contents objectAtIndex:indexPath.row];
    
    NSString* title = [elem objectForKey:FWDetailListViewFieldTitle];
    NSString* info = [elem objectForKey:FWDetailListViewFieldTitleInfo];
    NSString* value = [elem objectForKey:FWDetailListViewFieldValue];
    UIImage* icon = [elem objectForKey:FWDetailListViewFieldIcon];
    NSNumber* nobold = [elem objectForKey:FWDetailListViewFieldNoBold];
    NSNumber* lines = [elem objectForKey:FWDetailListViewFieldLines];
    NSNumber* swtch = [elem objectForKey:FWDetailListViewFieldSwitch];
    NSNumber* selected = [elem objectForKey:FWDetailListViewFieldSelected];
    NSNumber* progress = [elem objectForKey:FWDetailListViewFieldProgress];
    NSNumber* link = [elem objectForKey:FWDetailListViewFieldIsLink];
    NSNumber* back = [elem objectForKey:FWDetailListViewFieldIsBackLink];
    
    NSNumber* size = [elem objectForKey:FWDetailListViewFieldSize];
    if (size == nil)
        size = [NSNumber numberWithFloat:[UIFont labelFontSize]];
    
    UIColor* bgcolor = [elem objectForKey:FWDetailListViewFieldBGColor];
    if (!bgcolor)
        bgcolor = [UIColor whiteColor];
    
    static NSString *MyIdentifier = @"PITodoPreview";
    static NSInteger messageTag = 9998;
    static NSInteger roundedTag = 9999;
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1
                                       reuseIdentifier:MyIdentifier] autorelease];
        
        UILabel* message = [[[UILabel alloc] initWithFrame:CGRectZero] autorelease];
        message.font = [UIFont boldSystemFontOfSize:[UIFont labelFontSize]];
        message.tag = messageTag;
        message.textAlignment = UITextAlignmentCenter;
        message.backgroundColor = [UIColor clearColor];
        message.hidden = YES;
        [cell.contentView addSubview:message];
        
        FWRoundedLabel* label = [[[FWRoundedLabel alloc] initWithFrame:CGRectZero] autorelease];
        label.tag = roundedTag;
        [cell.contentView addSubview:label];
    }

    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    cell.accessoryType = UITableViewCellAccessoryNone;
    cell.accessoryView = nil;
    cell.backgroundColor = bgcolor;
    [[cell.contentView viewWithTag:messageTag] setHidden:YES];
    
    if (progress) {
        UIProgressView *progressBar = [[[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault] autorelease];
        progressBar.progress = [progress floatValue];
        CGRect size = progressBar.frame;
        size.size.width = iPad ? iPadSwitchSize.width : iPhoneSwitchSize.width;
        progressBar.frame = size;
        cell.accessoryView = progressBar;
    }
    else if (swtch) {
        UISwitch *switcher = [[[UISwitch alloc] initWithFrame:CGRectZero] autorelease];
        switcher.on = [swtch boolValue];
        switcher.tag = indexPath.section * 100 + indexPath.row;
        [switcher addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
        cell.accessoryView = switcher;
    }
    else if (selected) {
        if ([selected boolValue])
            cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }        
    else if (link || back) {
//        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
        cell.selectionStyle = UITableViewCellSelectionStyleBlue;
        NSBundle* bundle = [NSBundle bundleForClass:[self class]];
        FWColorIconView* icon = [[[FWColorIconView alloc] initWithFrame:CGRectMake(0, 0, 9, 14)] autorelease];
        icon.color = [UIColor darkGrayColor];
        icon.icon = [bundle pathForResource:link ? @"arrow-right" : @"arrow-left" ofType:@"png"];
        cell.accessoryView = icon;
    }        
    else if (NSString* message = [elem objectForKey:FWDetailListViewFieldMessage]) {
        UILabel* label = (UILabel*)[cell.contentView viewWithTag:messageTag];
        CGFloat cellInset = iPad ? iPadCellInset : iPhoneCellInset;
        CGFloat cellBorder = iPad ? iPadCellBorder : iPhoneCellBorder;
        
        label.font = [UIFont boldSystemFontOfSize:[size floatValue]];
        CGFloat width = tableView.frame.size.width - 2 * (cellInset + cellBorder);
        CGFloat height = [label.font leading]; 
        
        label.frame = CGRectMake(cellBorder, cellBorder, width, height);
        label.hidden = NO;
        label.text = message;
        
        UIColor* color = [elem objectForKey:FWDetailListViewFieldColor];
        if (color == nil)
            color = [UIColor darkTextColor];
        
        label.textColor = color;      
    }
    
    if (nobold == nil)
        cell.textLabel.font = [UIFont boldSystemFontOfSize:size.floatValue];
    else
        cell.textLabel.font = [UIFont systemFontOfSize:size.floatValue];
    
    cell.textLabel.text = title;
    cell.detailTextLabel.font = [UIFont systemFontOfSize:size.floatValue];
    cell.detailTextLabel.text = value;
    cell.imageView.image = icon;
    
    if ((value != nil) && ([value length] > 0)) {
        if (lines == nil) {
            cell.textLabel.numberOfLines = 1;
            cell.detailTextLabel.numberOfLines = 0;
        }
        else {
            cell.textLabel.numberOfLines = lines.intValue;
            cell.detailTextLabel.numberOfLines = lines.intValue;
        }			
        cell.detailTextLabel.lineBreakMode = UILineBreakModeWordWrap;
        cell.textLabel.textColor = [UIColor darkTextColor];
    }
    else {
        if (lines == nil) {
            cell.textLabel.numberOfLines = 0;
            cell.detailTextLabel.numberOfLines = 1;
        }
        else {
            cell.textLabel.numberOfLines = lines.intValue;
            cell.detailTextLabel.numberOfLines = lines.intValue;
        }			
        cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
        
        if (nobold != nil)
            cell.textLabel.textColor = cell.detailTextLabel.textColor;
        else {
            UIColor* color = [elem objectForKey:FWDetailListViewFieldColor];
            if (color == nil)
                color = [UIColor darkTextColor];
            cell.textLabel.textColor = color;
        }
    }
    
    FWRoundedLabel* roundLabel = (FWRoundedLabel*)[cell.contentView viewWithTag:roundedTag];
    if (info) {
        roundLabel.hidden = false;
        roundLabel.label.font = [UIFont systemFontOfSize:size.floatValue - 2];
        roundLabel.label.text = info;
        roundLabel.label.textColor = [UIColor blackColor];
        roundLabel.roundedColor = [UIColor lightGrayColor];

        CGSize constraintSize = [self tableView:tableView 
                 constraintForTextFieldWithIcon:nil
                                       progress:progress != nil
                                          swtch:swtch != nil
                                       selected:selected != nil];
        
        CGSize labelSize = [roundLabel sizeForHeight:roundLabel.label.font.leading];
        CGFloat cellHeight = [self tableView:tableView heightForRowAtIndexPath:indexPath];
        CGFloat cellBorder = iPad ? iPadCellBorder : iPhoneCellBorder;
        CGFloat indent = (cellHeight - labelSize.height) / 2.0;
        
        roundLabel.frame = CGRectMake(cellBorder + constraintSize.width - labelSize.width, 
                                      indent,
                                      labelSize.width,
                                      labelSize.height);
        
        [cell.contentView bringSubviewToFront:roundLabel];
    }
    else
        roundLabel.hidden = true;
    
    return cell;
}


// ******************************************************************************************
#pragma mark -
#pragma mark Animation and eye-candy

- (void)reloadData:(BOOL)animated
{
    [self.view reloadData];
    self.view.contentOffset = CGPointMake(0, reloadViewOffset);
     //scrollRectToVisible:CGRectMake(0, reloadViewOffset, 1, 1) animated:NO];
    
    if (animated) {
        CATransition *animation = [CATransition animation];
        [animation setType:kCATransitionFade];
        [animation setDuration:0.4];
        [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
        [animation setFillMode: @"extended"];
        
        [[self.view layer] addAnimation:animation forKey:@"reloadAnimation"];
    }
}


// ******************************************************************************************
#pragma mark -
#pragma mark Sub/super table selection hanndling

static NSString* const kStackList = @"list";
static NSString* const kStackCaption = @"caption";
static NSString* const kStackIndex = @"index";
static NSString* const kStackOffset = @"offset";

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSDictionary* section = [self.sections objectAtIndex:indexPath.section];
    NSArray* contents = [section objectForKey:FWDetailListViewSectionContents];
    NSDictionary* elem = [contents objectAtIndex:indexPath.row];
    
    NSNumber* link = [elem objectForKey:FWDetailListViewFieldIsLink];
    if (link) {
        NSLog(@"LI:PWTodo: row selected");
        
        [tableView deselectRowAtIndexPath:indexPath animated:NO];

        // Record where we are
        NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:self.list, kStackList,
                              [NSNumber numberWithInt:self.index], kStackIndex,
                              [NSNumber numberWithFloat:self.view.contentOffset.y], kStackOffset,
                              self.navBar.topItem.title, kStackCaption,
                              nil];
        [linkStack addObject:dict];
        
        // Set up data for the new view
        self.reloadViewOffset = 0;
        self.reloadViewAnimated = NO;
        self.list = [delegate listPageInfoForKey:link 
                                     currentPage:[self.list objectAtIndex:self.index]
                                    displayDepth:[self.linkStack count]
                                     application:application];
        self.index = 0;

        NSString* newCaption = @"";
        if ([delegate respondsToSelector:@selector(captionForListPage:forKey:displayDepth:application:)])
            newCaption = [delegate captionForListPage:self.list forKey:link displayDepth:[linkStack count] application:application];
            
        UINavigationItem* navItem = [[[UINavigationItem alloc] initWithTitle:newCaption] autorelease];

        NSBundle* bundle = [NSBundle bundleForClass:[self class]];
        UIBarButtonItem* doneBtn = [[[UIBarButtonItem alloc]
                                     initWithTitle:localize(bundle, @"Detail/Button/Done")
                                     style:UIBarButtonItemStyleBordered 
                                     target:self
                                     action:@selector(doneClicked)] autorelease];
        navItem.rightBarButtonItem = doneBtn;
        
        [self.navBar pushNavigationItem:navItem animated:YES];

        CATransition *animation = [CATransition animation];
        [animation setType:NavigationTransitionType];
        [animation setSubtype:kCATransitionFromRight];
        [animation setDuration:NavigationAnimationDuration];
        [animation setTimingFunction:[CAMediaTimingFunction functionWithName:NavigationTimingFunctionName]];
        
        [[self.view layer] addAnimation:animation forKey:NULL];
    }
    else if ([elem objectForKey:FWDetailListViewFieldIsBackLink]) {
        NSLog(@"LI:PWTodo: backlink row selected");
        
        [self.navBar popNavigationItemAnimated:YES];
    }
}

- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item
{
    if ([linkStack count] == 0)
        return NO;
    
    NSDictionary* info = [[[linkStack lastObject] retain] autorelease];
    [linkStack removeLastObject];
    NSArray* arrayValue = [info objectForKey:kStackList];
    NSNumber* indexValue = [info objectForKey:kStackIndex];
    NSNumber* offsetValue = [info objectForKey:kStackOffset];
    NSString* captionValue = [info objectForKey:kStackCaption];
    
    self.list = arrayValue;
//    self.caption = captionValue;
    self.reloadViewOffset = [offsetValue floatValue];
    self.reloadViewAnimated = NO;
    self.index = [indexValue intValue];
    
    CATransition *animation = [CATransition animation];
    [animation setType:NavigationTransitionType];
    [animation setSubtype:kCATransitionFromLeft];
    [animation setDuration:NavigationAnimationDuration];
    [animation setTimingFunction:[CAMediaTimingFunction functionWithName:NavigationTimingFunctionName]];
    
    [[self.view layer] addAnimation:animation forKey:NULL];
    
    return YES;
}


// ******************************************************************************************
#pragma mark -
#pragma mark Command button callbacks

- (void)cancelClicked
{
    if ([delegate cancelClicked:self.application sections:self.sections])
        [self.application.plugin.plugin dismissPreview];
}

- (void)doneClicked
{
    if ([delegate doneClicked:self.application sections:self.sections])
        [self.application.plugin.plugin dismissPreview];
}

- (void)selectClicked
{
    if ([delegate selectClicked:self.application sections:self.sections])
        [self.application.plugin.plugin dismissPreview];
}

- (void)switchChanged:(id)sender
{
    UISwitch* sw = (UISwitch*)sender;
    NSInteger section = (int)(sw.tag / 100);
    NSInteger row = (sw.tag % 100);

    NSDictionary* sect = [self.sections objectAtIndex:section];
    NSArray* contents = [sect objectForKey:FWDetailListViewSectionContents];
    NSMutableDictionary* element = [contents objectAtIndex:row];
    
    [element setObject:[NSNumber numberWithBool:sw.on] forKey:FWDetailListViewFieldSwitch];
}

- (void)navigateClicked:(id)sender
{
    UISegmentedControl *control = (UISegmentedControl *)sender;
    self.reloadViewOffset = 0;
    self.reloadViewAnimated = YES;

    if ([control selectedSegmentIndex] == 0)
        self.index = self.index - 1;
    else
        self.index = self.index + 1;
}

@end
